/*
//              INTEL CORPORATION PROPRIETARY INFORMATION
//  This software is supplied under the terms of a license  agreement or
//  nondisclosure agreement with Intel Corporation and may not be copied
//  or disclosed except in  accordance  with the terms of that agreement.
//    Copyright (c) 2006-2007 Intel Corporation. All Rights Reserved.
//
*/

#include "umc_defs.h"
#if defined (UMC_ENABLE_DV_VIDEO_ENCODER)

#include "umc_dv_enc_segment_writer.h"
#include "umc_dv_enc_compressor_def.h"
#include "umc_dv_video_encoder.h"

namespace UMC
{

DVSegmentWriter::DVSegmentWriter(void)
{
}

DVSegmentWriter::~DVSegmentWriter(void)
{
}

Status DVSegmentWriter::InitWriter(Ipp8s DSF, Ipp8u AppType)
{
    m_DSF = DSF;
    m_AppType = AppType;

    return UMC_OK;
}

void DVSegmentWriter::ReleaseWriter()
{
}

void DVSegmentWriter::WriteIDSection(DIFBlockIDData *pIDData, SectionType SCT, Ipp8u DIFBlockNum)
{
    (*pIDData).SCT = SCT;
    (*pIDData).Dseq = m_DIFSeqNum;
    (*pIDData).FSC = m_FSC;
    (*pIDData).FSP = m_FSP;
    (*pIDData).DBN = DIFBlockNum;

    (*pIDData).Res1 = 1;//1 reserved bit shall be set to 1
    (*pIDData).Res2 = 7;//3 reserved bits shall be set to 1
}

void DVSegmentWriter::WriteHeader()
{
    //header's DIF block number is always 0
    WriteIDSection((DIFBlockIDData*)m_pDest, Header, 0);

    //HeaderDIFBlockData *pHeaderData = (HeaderDIFBlockData *)(m_pDest + 3 /*size of block ID Data*/);
    Ipp8u *curPosition =(Ipp8u *)(m_pDest + 3 /*size of block ID Data*/);
    Ipp8u tempByte;

    //DSF: DIF Sequence flag:
    //DSF = 0 for 525/60 system (10 DIF sequences included in a channel)
    //DSF = 1 for 625/50 system (12 DIF sequences included in a channel)
    //(*pHeaderData).DSF = m_DSF;
    curPosition[0] = ((m_DSF & 0x01) << 7);
    curPosition[0] += 0x3f;
    //(*pHeaderData).zero = 0;

    //APTn, AP1n, AP2n and AP3n shall be identical as track application IDs (APTn = AP1n = AP2n = AP3n = 001), if
    //the source signal comes from  a digital VCR. If the source is unknown, all bits for these data shall be set
    //to 1.
    tempByte = (m_AppType & 0x01) ;
    tempByte += (m_AppType & 0x01) << 1;
    tempByte += (m_AppType & 0x01) << 2;
    tempByte += 0xf8;
    curPosition[1] = tempByte;
    curPosition[2] = tempByte;
    curPosition[3] = (tempByte & 0xfe);
    curPosition[4] = tempByte;

    //(*pHeaderData).APT =
    //    (*pHeaderData).AP1 =
    //    (*pHeaderData).AP2 =
    //    (*pHeaderData).AP3 = m_AppType;//The source is unknown

    //TF: Transmitting flag. TF1 - audio DIF blocks, TF2 - VAUX and Video DIF blocks, TF3 - subcode DIF blocks
    //TFn=0: Data shall be valid, TFn=1: Data shal be invalid
    //(*pHeaderData).TF1 = 1;//audio data is invalid
    //(*pHeaderData).TF2 = 0;//VAUX and video data is valid
    //(*pHeaderData).TF3 = 1;//subcode data is invalid


    //(*pHeaderData).Res1 = 63;//6 bits shall be set to 1
    //(*pHeaderData).Res2 = 31;//5 bits shall be set to 1
    //(*pHeaderData).Res3 =
    //    (*pHeaderData).Res4 =
    //    (*pHeaderData).Res5 = 15; //4 bits shall be set to 1

    memset( m_pDest + 3 /*size of block ID Data*/ + 5 /*size of header DIF block Data*/, 0xff, sizeof(DV_BLOCK) - 3 - 5);

    m_pDest += sizeof(DV_BLOCK);
}

void DVSegmentWriter::StartDIFSequence(Ipp8u DIFSeqNum, Ipp8u FSC, Ipp8u FSP/*=1*/)
{
    Ipp8u i;

    m_VideoDataDIFBlockNum = 0;
    m_AudioDataDIFBlockNum = 0;

    m_DIFSeqNum = DIFSeqNum;
    m_FSC = FSC;
    m_FSP = FSP;

    memset(m_pDest, 0xff, sizeof(DV_BLOCK) * 7);

    // Write 1 Header section
    WriteHeader();

    // Write 2 Subcode sections
    for (i = 0;i < 2;i++)
    {
        WriteIDSection((DIFBlockIDData*)m_pDest, Subcode, i);
        memset(m_pDest + 3, // size of block ID Data
               0xff,
               sizeof(DV_BLOCK) - 3);
        m_pDest += sizeof(DV_BLOCK);
    };

    // Write 3 VAUX sections
    for (i = 0;i < 3;i++)
    {
        WriteIDSection((DIFBlockIDData*)m_pDest, VAUX, i);
        memset(m_pDest + 3 /*size of block ID Data*/, 0xff, sizeof(DV_BLOCK) - 3);
        m_pDest += sizeof(DV_BLOCK);
    }
}

void DVSegmentWriter::WriteEmptyAudioSection()
{
    WriteIDSection((DIFBlockIDData *)m_pDest, Audio, m_AudioDataDIFBlockNum);
    memset(m_pDest + 3 /*size of block ID Data*/, 0xff, sizeof(DV_BLOCK) - 3);
    m_pDest += sizeof(DV_BLOCK);
    m_AudioDataDIFBlockNum++;
}

void DVSegmentWriter::SetDVSegment(struct DV_SEGMENT **lpDVSegment)
{
    Ipp16s i;

    if (0 == (m_VideoDataDIFBlockNum % 15))
    {
        WriteEmptyAudioSection();
    }

    *lpDVSegment = (DV_SEGMENT *) m_pDest;

    //Set ID sections for video DIF blocks
    for (i = 0; i<5; i++)
    {
        DIFBlockIDData *pCurrDVBlockIDData = (DIFBlockIDData *)&((*lpDVSegment)->m_EncodedMacroBlocks[i].id0);
        WriteIDSection(pCurrDVBlockIDData, Video, m_VideoDataDIFBlockNum);
        m_VideoDataDIFBlockNum++;
    }

    m_pDest += sizeof(DV_SEGMENT);
}

}//namespace UMC

#endif //(UMC_ENABLE_DV_VIDEO_ENCODER)
